#include "bsp_vision.h"
#include "bsp_usart.h"

// OpenMV or K210 机器视觉模块
// 定义openmv接受数组
int openmv[4];
int8_t OpenMV;
int m = 0;
uint8_t Res_K210_Color;

#if OpenMV_ON == 1 // 使能OpenMV接口
/**
 * @brief 串口1初始化函数, 并且开启NVIC中断配置 115200
 */
void USART1_OpenMV_Init(void)
{
    // GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);  // 使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能USART1时钟

    // 串口1对应引脚复用映射
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);  // GPIOA9复用为USART1
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); // GPIOA10复用为USART1

    // USART1端口配置
    /* PA9用于TX数据输出, PA10用于RX数据输入 */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9 | GPIO_Pin_10; // PA9 复用推挽输出
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;             // 复用功能
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;        // 速度100MHz
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;            // 推挽复用输出
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;             // 上拉
    GPIO_Init(GPIOA, &GPIO_InitStructure);                    // 初始化PA9，PA10
    // USART1 初始化设置
    USART_InitStructure.USART_BaudRate            = 115200;                         // 波特率设置
    USART_InitStructure.USART_WordLength          = USART_WordLength_8b;            // 字长为8位数据格式
    USART_InitStructure.USART_StopBits            = USART_StopBits_1;               // 一个停止位
    USART_InitStructure.USART_Parity              = USART_Parity_No;                // 无奇偶校验位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件数据流控制
    USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;  // 收发模式
    USART_Init(USART1, &USART_InitStructure);                                       // 初始化串口1

    USART_Cmd(USART1, ENABLE); // 使能串口1

    // Usart1 NVIC 配置
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启接收中断

    NVIC_InitStructure.NVIC_IRQChannel                   = USART1_IRQn; // 串口1中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;           // 抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 2;           // 子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;      // IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);                                     // 根据指定的参数初始化NVIC寄存器
}

void Openmv_Data(void)
{
    OpenMV = openmv[2];
}

void Openmv_Receive_Data(int16_t data)
{
    static uint8_t state = 0;
    if (state == 0 && data == 0xb3) {
        state     = 1;
        openmv[0] = data;
    } else if (state == 1 && data == 0xb2) {
        state     = 2;
        openmv[1] = data;
    } else if (state == 2) {
        state     = 3;
        openmv[2] = data;
    } else if (state == 3) {
        if (data == 0x5b) {
            state     = 0;
            openmv[3] = data;
            Openmv_Data();
            data = 0;
        } else if (data != 0x5b) {
            state = 0;
            for (m = 0; m < 4; m++) {
                openmv[m] = 0x00;
            }
        }
    } else {
        state = 0;
        data  = 0;
        for (m = 0; m < 4; m++) {
            openmv[m] = 0x00;
        }
    }
}

void USART1_IRQHandler(void) // 串口1中断服务程序
{
    uint8_t com_data;
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
        USART_ClearFlag(USART1, USART_FLAG_RXNE);
        com_data = USART_ReceiveData(USART1);
        Openmv_Receive_Data(com_data);
        Openmv_Data();
        com_data = 0;
    }
}

#elif MaixCAM_ON == 1
/**
 * @brief MaixCAM K210 IO口初始化
 *
 */
void GPIO_MAIXCAM_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;  // 输入模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽输出
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; // 速度选择

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
}
/**
 * @brief 读取K210的数据 黑色返回1 蓝色返回2 绿色返回3 错误返回0
 *
 * @return uint8_t Res_K210_Color 收到的数据
 */
uint8_t K210_Color(void)
{
    if (GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_0) == SET &&
        GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_1) == RESET &&
        GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_2) == RESET) {
        Res_K210_Color = 1;
    } else if (GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_0) == RESET &&
               GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_1) == SET &&
               GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_2) == RESET) {
        Res_K210_Color = 2;
    } else if (GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_0) == RESET &&
               GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_1) == RESET &&
               GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_2) == SET) {
        Res_K210_Color = 3;
    } else {
        Res_K210_Color = 0; // 错误
    }
    return Res_K210_Color;
}
#endif